#include "hal_socket.h"
#include "usart.h"
#include "hal_tlv.h"
#include <common.h>
#include "sys_log.h"
#include "tlv_cmd.h"
#include "tlv_pack_com.h"

extern int (*laser_func_callback_fun[FUNC_LASER_TYPE_COUNT_E])(struct TLVPacket *);
extern int (*motor_func_callback_fun[FUNC_MOTOR_TYPE_COUNT_E])(struct TLVPacket *);

extern DMA_HandleTypeDef hdma_usart2_rx;
extern struct PacketQueue g_MyQueue;
extern uint16_t g_DeviceID;

uint8_t g_Uart2_Buff[MSG_BUFFER_MAX_SIZE];

void endianSwapDeal(void *data, size_t size);

void hal_uart_init()
{
    //使能空闲中断
    __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);

    // 开启DMA接收中断
    HAL_UART_Receive_DMA(&huart2, (uint8_t *)g_Uart2_Buff, sizeof(g_Uart2_Buff));

    // 启用处理器的中断功能，使其能够响应并处理中断信号
    __enable_irq();
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART2)
    {
        if ((__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE) != RESET))
        {
            uint16_t Uart2_Rcv_Bytes = 0;
            uint8_t Uart2_Rcv_Buff[MSG_BUFFER_MAX_SIZE];
            memset(Uart2_Rcv_Buff, 0, MSG_BUFFER_MAX_SIZE);

            struct TLVPacket unpack_packet;
            memset(&unpack_packet, 0, sizeof(struct TLVPacket));

            // 停止DMA接收中断
            HAL_UART_DMAStop(&huart2);

            // 获取接收到的字节数
            // __HAL_DMA_GET_COUNTER(&hdma_usart2_rx)和hdma_usart2_rx.Instance->NDTR同一个意思
            Uart2_Rcv_Bytes = MSG_BUFFER_MAX_SIZE - hdma_usart2_rx.Instance->NDTR;

            // 拷贝到接收buf
            memcpy(Uart2_Rcv_Buff, g_Uart2_Buff, sizeof(g_Uart2_Buff));

            // 对获取的指令进行解析
            uint8_t ret = hal_unpack(Uart2_Rcv_Buff, Uart2_Rcv_Bytes, &unpack_packet);
            // 指令解析正确则入队列
            if (ret)
            {
                enqueue(&g_MyQueue, &unpack_packet);
            }

            // hal_UsartSendBuffer(Uart2_Rcv_Buff, Uart2_Rcv_Bytes, USART_TYPE_2);

            // 清空全局串口接收数据buffer
            memset(g_Uart2_Buff, 0, sizeof(g_Uart2_Buff));

            // 清除空闲标志位
            __HAL_UART_CLEAR_IDLEFLAG(&huart2);

            // 打开DMA接收中断
            HAL_UART_Receive_DMA(&huart2, (uint8_t *)g_Uart2_Buff, sizeof(g_Uart2_Buff));
        }
    }
    else if (huart->Instance == USART1)
    {
        if ((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) != RESET))
        {
            __HAL_UART_CLEAR_IDLEFLAG(&huart1);
        }
    }
}

void hal_SendPacketToUSART(struct TLVPacket *packet)
{
    // udp发送buf：足够大小的缓冲区
    uint8_t frame_buffer[MSG_BUFFER_MAX_SIZE] = {0};
    // 组成一个完整的指令帧，返回指令帧长度
    uint16_t frame_length = hal_pack(g_DeviceID, packet, frame_buffer);
    // 发送数据
    hal_UsartSendBuffer(frame_buffer, frame_length, USART_TYPE_2);
}

void hal_UsartSendBuffer(uint8_t *pdata_in, uint16_t len, UsartTypeEn UsartNum)
{
    switch (UsartNum)
    {
    case USART_TYPE_1:
#ifdef UASRT1_IS_ENABLE
        // RS232串口
        HAL_UART_Transmit(&huart1, pdata_in, len, 0xff);
#endif
        break;

    case USART_TYPE_2:
        // RS485串口
        HAL_GPIO_TogglePin(USART2_DE_GPIO_Port, USART2_DE_Pin);
        systick_delay_ms(10);
        HAL_UART_Transmit_DMA(&huart2, pdata_in, len);
        systick_delay_ms(20);
        HAL_GPIO_TogglePin(USART2_DE_GPIO_Port, USART2_DE_Pin);
        break;

    default:
        break;
    }
}

void enqueue(struct PacketQueue *queue, struct TLVPacket *packet)
{
    // 连续存满 Queue_MAX_SIZE 个都没有取走，全部丢弃 直接从0开始
    if (queue->itemcount == Queue_MAX_SIZE)
    {
        queue->front     = 0;
        queue->rear      = -1;
        queue->itemcount = 0;
    }
    // 计算当前队列的rear值
    queue->rear = (queue->rear + 1) % Queue_MAX_SIZE;
    // 拷贝到队列中
    memcpy(&queue->items[queue->rear], packet, sizeof(struct TLVPacket));
    // 计数 队列中未执行的元素++
    queue->itemcount++;

    SLOG_I("lasermotor enqueue maxsize: %d, nowsize: %d, module: %s, cmd: %#x \t\r\n", Queue_MAX_SIZE, queue->itemcount, 
    (packet->tagmodule == DEVICE_TYPE_MOTOR_E ? "motor" : packet->tagmodule == DEVICE_TYPE_LASER_E ? "laser" : "error device"), 
    packet->tagcmd);
}

void dequeue(struct PacketQueue *queue, struct TLVPacket *packet)
{
    //队列拷贝到packet中
    memcpy(packet, &queue->items[queue->front], sizeof(struct TLVPacket));
    // 计算当前队列的front值
    queue->front = (queue->front + 1) % Queue_MAX_SIZE;
    // 计数 队列中未执行的元素--
    queue->itemcount--;

    SLOG_I("lasermotor dequeue maxsize: %d, nowsize: %d, module: %s, cmd: %#x \t\r\n", Queue_MAX_SIZE, queue->itemcount, 
    (packet->tagmodule == DEVICE_TYPE_MOTOR_E ? "motor" : packet->tagmodule == DEVICE_TYPE_LASER_E ? "laser" : "error device"), 
    packet->tagcmd);
}

// 判断队列是否为空
_Bool isQueueEmpty(struct PacketQueue *queue) { return queue->itemcount == 0; }

// TLV协议下进行激光/电衰指令分流
// static void *now_cb_hd = null;
void ModuleDivide(struct TLVPacket *packet)
{
    // tag两个字节：第一个字节是 激光/电衰分类，第二个字节是 具体指令
    uint8_t ModuleType = packet->tagmodule;
    uint8_t funcCmd    = packet->tagcmd;

    if (ModuleType == MODULE_CHOSE_TYPE)
    {
#if MODEL_CHOICE == MODEL_LASER_DFB || MODEL_CHOICE == MODEL_LASER_TA
        // 激光指令，防止指令不正确踩内存
        if(funcCmd < FUNC_LASER_TYPE_COUNT_E)
        {
            (*laser_func_callback_fun[funcCmd])(packet);
        }
#elif MODEL_CHOICE == MODEL_MOTOR
        // 电衰指令，防止指令不正确踩内存
        if(funcCmd < FUNC_MOTOR_TYPE_COUNT_E)
        {
            (*motor_func_callback_fun[funcCmd])(packet);
        }
#endif
    }
}

/* 可选*/
void endianSwapDeal(void *data, size_t size)
{
    uint16_t i = 0;

    uint32_t *pbuf = (uint32_t *)data;

    do
    {
        swapEndianUint32AndCopy(pbuf);
        pbuf++;
        i += 4;
    }
    while (i < size);
}